﻿using System;
using BlockLogic.Impl.Blocks.Checker;
using BlockLogic.Impl.Blocks.Checker.Strategy;
using BlockLogic.Impl.Blocks.Generator;
using BlockLogic.Impl.Blocks.ServiceDevice;
using BlockLogic.Impl.Enum;
using BlockLogic.Interface.Blocks;
using BlockLogic.Interface.Factory;
using ComputationalCore.Impl.RandomGenerator.Factory;
using ComputationalCore.Impl.RandomGenerator.Enum;


namespace BlockLogic.Impl.Factory
{
    public class BlockFactory : IBlockFactory
    {
        private static BlockFactory _instance = new BlockFactory();

        private BlockFactory() { }

        public static IBlockFactory GetInstance()
        {
            return _instance;
        }

        public IBlock Create(Guid id, BlockType type)
        {
            var factory = RandomGeneratorFactory.GetInstance();

            switch (type)
            {
                //Generators
                case BlockType.GENERATOR_UNIFORM:
                    {
                        var generator = new Generator(id, BlockType.GENERATOR_UNIFORM)
                                            {RandomGenerator = factory.Create(RandomGeneratorType.UNIFORM)};
                        return generator;
                    }
                case BlockType.GENERATOR_ERLANG:
                    {
                        var generator = new Generator(id, BlockType.GENERATOR_ERLANG)
                                            {RandomGenerator = factory.Create(RandomGeneratorType.ERLANG)};
                        return generator;
                    }
                case BlockType.GENERATOR_GAUSSIAN:
                    {
                        var generator = new Generator(id, BlockType.GENERATOR_GAUSSIAN)
                                            {RandomGenerator = factory.Create(RandomGeneratorType.GAUSSIAN)};
                        return generator;
                    }
                case BlockType.GENERATOR_POISSON:
                    {
                        var generator = new Generator(id, BlockType.GENERATOR_POISSON)
                                            {RandomGenerator = factory.Create(RandomGeneratorType.POISSON)};
                        return generator;
                    }
                //Checkers
                case BlockType.CHECKER_UNIFORM:
                    {
                        var checker = new CheckerBlock(id, BlockType.CHECKER_UNIFORM) 
                                          {Strategy = new UniformChecking()};
                        return checker;
                    }
                case BlockType.CHECKER_EXPONENTIAL:
                    {
                        var checker = new CheckerBlock(id, BlockType.CHECKER_EXPONENTIAL)
                                          {Strategy = new ExponentialChecking()};
                        return checker;
                    }
                case BlockType.CHECKER_GAUSSIAN:
                    {
                        var checker = new CheckerBlock(id, BlockType.CHECKER_GAUSSIAN)
                                          {Strategy = new GaussianChecking()};
                        return checker;
                    }

                //Service Device

                    //With Queue
                case BlockType.SERVICE_DEVICE_WITH_QUEUE_UNIFORM:
                    {
                        var service = new ServiceDeviceWithQueue(id, BlockType.SERVICE_DEVICE_WITH_QUEUE_UNIFORM)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.UNIFORM)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_QUEUE_POISSON:
                    {
                        var service = new ServiceDeviceWithQueue(id, BlockType.SERVICE_DEVICE_WITH_QUEUE_POISSON)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.POISSON)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_QUEUE_GAUSSIAN:
                    {
                        var service = new ServiceDeviceWithQueue(id, BlockType.SERVICE_DEVICE_WITH_QUEUE_GAUSSIAN)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.GAUSSIAN)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_QUEUE_ERLANG:
                    {
                        var service = new ServiceDeviceWithQueue(id, BlockType.SERVICE_DEVICE_WITH_QUEUE_ERLANG)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.ERLANG)};
                        return service;
                    }

                    //With Waiting
                case BlockType.SERVICE_DEVICE_WITH_WAITING_UNIFORM:
                    {
                        var service = new ServiceDeviceWithWaiting(id, BlockType.SERVICE_DEVICE_WITH_WAITING_UNIFORM)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.UNIFORM)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_WAITING_POISSON:
                    {
                        var service = new ServiceDeviceWithWaiting(id, BlockType.SERVICE_DEVICE_WITH_WAITING_POISSON)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.POISSON)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_WAITING_GAUSSIAN:
                    {
                        var service = new ServiceDeviceWithWaiting(id, BlockType.SERVICE_DEVICE_WITH_WAITING_GAUSSIAN)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.GAUSSIAN)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_WAITING_ERLANG:
                    {
                        var service = new ServiceDeviceWithWaiting(id, BlockType.SERVICE_DEVICE_WITH_WAITING_ERLANG)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.ERLANG)};
                        return service;
                    }

                //With Loss
                case BlockType.SERVICE_DEVICE_WITH_LOSS_UNIFORM:
                    {
                        var service = new ServiceDeviceWithLoss(id, BlockType.SERVICE_DEVICE_WITH_LOSS_UNIFORM)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.UNIFORM)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_LOSS_POISSON:
                    {
                        var service = new ServiceDeviceWithLoss(id, BlockType.SERVICE_DEVICE_WITH_LOSS_POISSON)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.POISSON)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_LOSS_GAUSSIAN:
                    {
                        var service = new ServiceDeviceWithLoss(id, BlockType.SERVICE_DEVICE_WITH_LOSS_GAUSSIAN)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.GAUSSIAN)};
                        return service;
                    }
                case BlockType.SERVICE_DEVICE_WITH_LOSS_ERLANG:
                    {
                        var service = new ServiceDeviceWithLoss(id, BlockType.SERVICE_DEVICE_WITH_LOSS_ERLANG)
                                          {RandomGenerator = factory.Create(RandomGeneratorType.ERLANG)};
                        return service;
                    }

                default:
                    return default(IBlock);
            }
        }
    }
}
